Ruby 日記 22日目: ブロック付きメソッドに対して Proc オブジェクトを & をつけて渡す
次のプログラムを実行すると215が表示されます。
__(1)__に適切な選択肢を選んでください。
code:rb
val = 100
def method(val)
yield(15 + val)
end
_proc = Proc.new{|arg| val + arg }
p method(val, __(1)__)
選択肢:
&_proc.to_proc
_proc.to_proc
_proc
&_proc
解説:
Procについて理解しないとね
ブロックをコンテキスト(ローカル変数のスコープやスタックフレーム)とともにオブジェクト化した手続きオブジェクトです。
ほん?こう言われるとよくわからないわね。
Proc は ローカル変数のスコープを導入しないことを除いて 名前のない関数のように使えます。
これはよくわかるわ
ダイナミックローカル変数は Proc ローカルの変数として使えます。
Proc がローカル変数のスコープを保持していることは以下の例で 変数 var を参照できていることからわかります。
code:rb
var = 1
$foo = Proc.new { var }
var = 2
def foo
$foo.call
end
p foo # => 2
わかりやすい例だね
手続きオブジェクトを中断して、呼出し元(呼び出しブロックでは yield、それ以外では Proc#call) へジャンプし値を返すには next を使います。break や return ではありません。
code:rb
def foo
f = Proc.new{
next 1
2
}
end
中断して...(略)...値を返すには next を使います。break や return ではありません。 そうだね。
これ問題にできそうね。
ブロック付きメソッドに対して Proc オブジェクトを & を指定して渡すと 呼び出しブロックのように動作します。
なるほどねぇ
今回の問題に戻ると、
code:rb
def method(val)
yield(15 + val)
end
がブロック付きのメソッド。
で、これに対してProcオブジェクト _proc = Proc.new{|arg| val + arg } を引数として渡す、というシーンだ。
code:rb
p method(val, __(1)__)
Procオブジェクトをそのまま引数に渡すことはできないので、&をつけてブロック呼び出しのようにして渡す
ふむうなるほど
この辺がいまだに雰囲気だけでやってるんだよな
本読んでみるかな〜
to_proc -> self
self を返します。
とのこと。
Procオブジェクトに&をつけたものについても、それ自体はto_procメソッドを持つんだなぁ。
/icons/hr.icon
code:gold/ex22/choice01.rb
val = 100
def method(val)
yield(15 + val)
end
_proc = Proc.new{|arg| val + arg }
p method(val, &_proc.to_proc)
code:sh
# ruby gold/ex22/choice01.rb
215
/icons/hr.icon
code:gold/ex22/choice02.rb
val = 100
def method(val)
yield(15 + val)
end
_proc = Proc.new{|arg| val + arg }
p method(val, _proc.to_proc)
code:sh
# ruby gold/ex22/choice02.rb
gold/ex22/choice02.rb:3:in `method': wrong number of arguments (2 for 1) (ArgumentError)
from gold/ex22/choice02.rb:9:in `<main>'
/icons/hr.icon
code:gold/ex22/choice03.rb
val = 100
def method(val)
yield(15 + val)
end
_proc = Proc.new{|arg| val + arg }
p method(val, _proc)
code:sh
# ruby gold/ex22/choice03.rb
gold/ex22/choice03.rb:3:in `method': wrong number of arguments (2 for 1) (ArgumentError)
from gold/ex22/choice03.rb:9:in `<main>'
/icons/hr.icon
code:gold/ex22/choice04.rb
val = 100
def method(val)
yield(15 + val)
end
_proc = Proc.new{|arg| val + arg }
p method(val, &_proc)
code:sh
# ruby gold/ex22/choice04.rb
215
よって正解は「&_proc.to_proc」と「&_proc」だね
/icons/hr.icon
で、つまりこれって、こういうこと
code:gold/ex22/sample.rb
def method(val)
yield(15 + val)
end
p method(100){|arg| 100 + arg }
yield(115) で arg = 115 で { 100 + 115 } が処理されて 215 みたいな